package QC.MessageBox.common;

import QC.MessageBox.enums.ActiveLimit;
import QC.MessageBox.wxmpase.AesException;
import QC.MessageBox.wxmpase.WXBizMsgCrypt;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.json.JsonObject;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Andaren on 2017/3/31.
 * userd for: 微信工具方法类
 */
public class WxUtils {

    private static final Logger logger = LoggerFactory.getLogger(WxUtils.class);

    /**
     * 验证请求来源(明文方式)
     * @param request
     * @return
     */
    public static boolean checkRequest(HttpServerRequest request) {
        // 获取参数
        String signature = request.getParam("signature");   // 签名
        String timestamp = request.getParam("timestamp");   // 时间戳
        String nonce = request.getParam("nonce");           // 随机数
        if (StringUtils.isNotBlank(signature) &&
                StringUtils.isNotBlank(timestamp) &&
                StringUtils.isNotBlank(nonce)) {
            // 1）将token、timestamp、nonce三个参数进行字典序排序
            String[] paramArrays = new String[]{Constants.TOKEN, timestamp, nonce};
            Arrays.sort(paramArrays);
            // 2）将三个参数字符串拼接成一个字符串进行sha1加密
            String sortedStr = paramArrays[0] + paramArrays[1] + paramArrays[2];
            // 3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
            String sha1Str = DigestUtils.sha1Hex(sortedStr);
            return sha1Str.equals(signature);
        }
        return false;
    }

    /**
     * 验证请求来源(密文方式)
     * @param request
     * @return
     */
    public static String checkURL(HttpServerRequest request) {
        String result = null;
        try {
            // TODO 根据请求的URL地址获取APPId
            WXBizMsgCrypt crypt = new WXBizMsgCrypt(Constants.TOKEN, Constants.ENCODINGAESKEY, null);
            // 获取参数
            String signature = request.getParam("signature");   // 签名
            String timestamp = request.getParam("timestamp");   // 时间戳
            String nonce = request.getParam("nonce");           // 随机数
            String echoStr = request.getParam("echoStr");
            if (StringUtils.isNotBlank(signature) &&
                    StringUtils.isNotBlank(timestamp) &&
                    StringUtils.isNotBlank(nonce) &&
                    StringUtils.isNotBlank(echoStr)) {
                result = crypt.verifyUrl(signature, timestamp, nonce, echoStr);
            }

        } catch (AesException aesExp) {
            System.out.println("URL 验证失败");
            aesExp.printStackTrace();
        }
        return result;
    }

    /**
     * 解密消息，获取消息内容
     * @param request
     * @param bodyXML
     * @param appId
     * @return
     */
    public static String getWxBizMsgCryptedStr(HttpServerRequest request, String bodyXML, String appId) {
        if (StringUtils.isBlank(bodyXML) ||
                StringUtils.isBlank(appId) ||
                request == null) {
            logger.info("解密参数异常["
                    + "request="+request
                    + ",bodyXML=" +bodyXML
                    + ", appId="+appId+"]");
            return null;
        }
        String content = null;
        String msgSignature = request.getParam("msg_signature");// 消息体签名
        String encryptType = request.getParam("encrypt_type");  // 消息加密类型（raw/aes）

        String timestamp = request.getParam("timestamp");       // 时间戳
        String nonce = request.getParam("nonce");               // 随机数

        if (StringUtils.isNotBlank(encryptType)) {
            try {
                WXBizMsgCrypt pc = new WXBizMsgCrypt(Constants.TOKEN, Constants.ENCODINGAESKEY, appId);
                content = pc.decryptMsg(msgSignature, timestamp, nonce, bodyXML);
            } catch (AesException aes) {
                logger.error("请求内容加解密异常：{}", aes.getMessage());
            }
        }
        return content;
    }

    /**
     *  生成回复微信用户的json消息
     * @param openId    // 要回复的微信用户
     * @param msgType   // 消息类型
     * @param replyMsgContent  // 消息体
     * @return
     */
    public static JsonObject buildReplyJsonMsg(String openId, String msgType, String replyMsgContent) {
        JsonObject jsonMsg = new JsonObject();
        jsonMsg.put("touser", openId);
        jsonMsg.put("msgtype", msgType);
        JsonObject contentJson = new JsonObject();
        switch (msgType) {
            case "text" :
                contentJson.put("content", replyMsgContent);
                break;
            case "image" :
                contentJson.put("media_id", replyMsgContent);
                break;

            default:
        }
        jsonMsg.put(msgType, contentJson);
        return jsonMsg;
    }

    /**
     * emoji表情转换(hex -> utf-16)
     *
     * @param hexEmoji
     * @return
     */
    public static String emoji(int hexEmoji) {
        return String.valueOf(Character.toChars(hexEmoji));
    }

    public static String enEmoji(String msg) {
        String qqfaceRegex = "/::\\)|/::~|/::B|/::\\||/:8-\\)|/::<|/::$|/::X|/::Z|/::'\\(|/::-\\||/::@|/::P|/::D|/::O|/::\\(|/::\\+|/:--b|/::Q|/::T|/:,@P|/:,@-D|/::d|/:,@o|/::g|/:\\|-\\)|/::!|/::L|/::>|/::,@|/:,@f|/::-S|/:\\?|/:,@x|/:,@@|/::8|/:,@!|/:!!!|/:xx|/:bye|/:wipe|/:dig|/:handclap|/:&-\\(|/:B-\\)|/:<@|/:@>|/::-O|/:>-\\||/:P-\\(|/::'\\||/:X-\\)|/::\\*|/:@x|/:8\\*|/:pd|/:<W>|/:beer|/:basketb|/:oo|/:coffee|/:eat|/:pig|/:rose|/:fade|/:showlove|/:heart|/:break|/:cake|/:li|/:bome|/:kn|/:footb|/:ladybug|/:shit|/:moon|/:sun|/:gift|/:hug|/:strong|/:weak|/:share|/:v|/:@\\)|/:jj|/:@@|/:bad|/:lvu|/:no|/:ok|/:love|/:<L>|/:jump|/:shake|/:<O>|/:circle|/:kotow|/:turn|/:skip|/:oY|/:#-0|/:hiphot|/:kiss|/:<&|/:&>";
        Pattern p = Pattern.compile(qqfaceRegex);
        Matcher m = p.matcher(msg);
        /*msg.
        if (m.matches()) {
            msg = "";
        }*/
        return msg;
    }

    /**
     * @Description 将字符串中的emoji表情转换成可以在utf-8字符集数据库中保存的格式（表情占4个字节，需要utf8mb4字符集）
     * @param str
     * 待转换字符串
     * @return 转换后字符串
     * @throws UnsupportedEncodingException
     * exception
     */
    public static String emojiConvert1(String str)
            throws UnsupportedEncodingException {
        String patternString = "([\\x{10000}-\\x{10ffff}\ud800-\udfff])";

        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while(matcher.find()) {
            System.out.println("|->" + matcher.group(1));
            matcher.appendReplacement(sb, matcher.group(1));

        }
        matcher.appendTail(sb);
        System.out.println("emojiConvert " + str + " to " + sb.toString()
                + ", len：" + sb.length());
        return sb.toString();
    }

    /**
     * @Description 还原utf8数据库中保存的含转换后emoji表情的字符串
     * @param str
     * 转换后的字符串
     * @return 转换前的字符串
     * @throws UnsupportedEncodingException
     * exception
     */
    public static String emojiRecovery2(String str)
            throws UnsupportedEncodingException {
        String patternString = "\\[\\[(.*?)\\]\\]";

        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(str);

        StringBuffer sb = new StringBuffer();
        while(matcher.find()) {
            try {
                matcher.appendReplacement(sb,
                        URLDecoder.decode(matcher.group(1), "UTF-8"));
            } catch(UnsupportedEncodingException e) {
                logger.error("emojiRecovery error", e);
                throw e;
            }
        }
        matcher.appendTail(sb);
        logger.debug("emojiRecovery " + str + " to " + sb.toString());
        return sb.toString();
    }

    // public BaseWXMsg

    /**
     * 验证用户是否仍在线
     * @param lastActiveTime
     * @return
     */
    public static Long checkUserOnline(Long lastActiveTime) {
        Long currentTimestamp = PeriodicTime.getCurrentTimestamp();
        Long distance = currentTimestamp - lastActiveTime;
        return ((ActiveLimit.ACTIVE_LIMIT.getLimit() - distance) / 3600);
    }

    public static void main(String[] args) {
        String ss = "\uE401\uE412\uE404 \uE412";
        String sss = "\uD83D\uDE02";
        try{
            System.out.println(ss);
            System.out.println(sss);
        }catch (Exception e){
            e.printStackTrace();
        }

        byte[] a = new String("\uD83D\uDE02").getBytes();
        System.out.println(Hex.encodeHexString(a));
        System.out.println(emoji(0x1F602));
        try {
            System.out.println(emojiConvert1(ss + "什么" + emoji(0x270C)));
        }catch (Exception e) {
            e.printStackTrace();
        }

    }
}
